﻿/* *
 * =============================================================================
 * File Name:               Page.xaml.cs
 * Programmer:              Ken Watts
 * Creation Date:           9/20/2008
 * =============================================================================
 * Description:             Implementation of the main program.
 *                          Generates the Koch curve
 * =============================================================================
 * Modification Date:       9/20/2008 - Initial Revision
 * =============================================================================
 * */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace KochCurve
{
    public partial class Page : UserControl
    {
        // Constants
        const int k_int_initial_points = 2;
        const int k_int_triangle_points = 3;
        const int k_int_max_iterations = 6;
        const double k_dbl_stroke_thickness = 1;
        const double k_dbl_start_point_x = 0;
        const double k_dbl_start_point_y = 100;
        const double k_dbl_end_point_x = 300;
        const double k_dbl_end_point_y = 100;

        PointCollection curvePoints;
        int numPoints, itrCount;
        Brush strokeBrush = new SolidColorBrush(Colors.Black);

        public Page()
        {
            InitializeComponent();
            // Draw the initial line
            initializeCurve();
        }

        private void drawCurve()
        {
            Polyline pl = new Polyline();
            pl.Points = curvePoints;
            pl.Stroke = strokeBrush;
            pl.StrokeThickness = k_dbl_stroke_thickness;
            canvasBackground.Children.Add(pl);
        }

        private void initializeCurve()
        {
            curvePoints = new PointCollection();
            numPoints = k_int_initial_points;
            itrCount = 0;
            ButtonNextIteration.IsEnabled = true;
            // Setup the initial line
            curvePoints.Add(new Point(k_dbl_start_point_x,k_dbl_start_point_y));
            curvePoints.Add(new Point(k_dbl_end_point_x,k_dbl_end_point_y));
            // Draw the curve
            drawCurve();
        }

        private void ButtonNextIteration_Click(object sender, RoutedEventArgs e)
        {
            /*
             * Adapted from algorithm defined here: http://www.efg2.com/Lab/Library/UseNet/1997/0219.txt
                                      s




                        a        r         t        b
             */
            const double factor = 0.288675135; // SQRT(3) / 6 
            Point a, b, r, s, t, middle;
            double xDelta,yDelta;

            // Clear the canvas
            canvasBackground.Children.Clear();
            // Set up the new plot points
            PointCollection newCurvePoints=new PointCollection();
            for (int i = 0; i < numPoints - 1; i++)
            {
                // Init. points a & b
                a = curvePoints[i];
                b = curvePoints[i + 1];
                // Add first point
                newCurvePoints.Add(a);
                // Calculate the triangle points
                r = new Point();
                s = new Point();
                t = new Point();
                middle = new Point();
                r.X = (2.0 * a.X + b.X) / 3.0;
                r.Y = (2.0 * a.Y + b.Y) / 3.0;
                t.X = (a.X + 2.0 * b.X) / 3.0;
                t.Y = (a.Y + 2.0 * b.Y) / 3.0;
                middle.X = (a.X + b.X) / 2.0;
                middle.Y = (a.Y + b.Y) / 2.0;
                xDelta = curvePoints[i + 1].X - a.X;
                yDelta = curvePoints[i + 1].Y - a.Y;
                s.X = middle.X + factor*yDelta;
                s.Y = middle.Y - factor*xDelta;
                // Add the triangle points
                newCurvePoints.Add(r);
                newCurvePoints.Add(s);
                newCurvePoints.Add(t);
            }
            // Add the last point
            newCurvePoints.Add(curvePoints[numPoints-1]);
            // Reset the curve points
            curvePoints = newCurvePoints;
            numPoints = numPoints + ((numPoints - 1) * k_int_triangle_points);
            // Draw the curve
            drawCurve();
            if (++itrCount >= k_int_max_iterations)
                ButtonNextIteration.IsEnabled = false;
        }

        private void ButtonReset_Click(object sender, RoutedEventArgs e)
        {
            // Clear the canvas
            canvasBackground.Children.Clear();
            initializeCurve();
        }
        
    }
}
